import pygame, sys, random
from pygame.locals import *
import time
pygame.init()

windowSurface = pygame.display.set_mode((600, 500), 0, 32)
pygame.display.set_caption('Solitaire')
DARKGREEN = (0,100,0)

back = pygame.image.load ("classic-cards\\back.png")
acebackground = pygame.image.load ("classic-cards\\AceCardImage.png")

images = []
for i in range (1, 53):
    images.append (pygame.image.load ("classic-cards\\" + str (i) + ".png"))

def getCardImage(rankSuit):
    return images[rankSuit[0] * 4 + rankSuit[1]]

CLUBS = 0
SPADES = 1
HEARTS = 2
DIAMONDS = 3
ACE = 0
KING = 1
QUEEN = 2
JACK = 3
TEN = 4
NINE = 5
EIGHT = 6
SEVEN = 7
SIX = 8
FIVE = 9
FOUR = 10
THREE = 11
TWO = 12
draggedcard = []

class Card:
    def __init__(self,rank,suit):
        self.rank = rank
        self.suit = suit
        self.faceup = False
    
    def drawAt(self, x, y):
        if self.faceup:
            windowSurface.blit(getCardImage((self.rank, self.suit)), Rect(x, y, 72, 96))
        else:
            windowSurface.blit(back, Rect(x, y, 72, 96)) 
            
allCards = []
for suit in[CLUBS,SPADES,HEARTS,DIAMONDS]:
    for rank in range(0, 13):
        allCards.append(Card(rank,suit))

random.shuffle(allCards)

def Shuffle(event):
    while shuffle():
        if facedownPile.collasped():
            random.shuffle(allCards)
            facedownPile = True
        return True

class Pile:
    def __init__(self, x, y, collapsed):
        self.cards = []
        self.collapsed = collapsed
        self.x = x
        self.y = y
        
    def draw(self):
        windowSurface.blit(acebackground,pygame.Rect(self.x, self.y, 72, 96))
        if self.collapsed:
            for i in range(0,len(self.cards)):
                if not self.cards[i] in draggedcard:
                    self.cards[i].drawAt(self.x, self.y)
        else:
            for i in range(0, len(self.cards)):
                if not self.cards[i] in draggedcard:
                    self.cards[i].drawAt(self.x, self.y + 15*i)               
                
    def boundingRect(self):
        if self.collapsed:
            return Rect(self.x, self.y, 72, 96)
        else:
            return Rect(self.x, self.y, 72, 96+15*max(0, len(self.cards)-1))
    
    def rectangle(self):
        if self.collapsed:
            return Rect (self.x,self.y,72,96)
        else:
            return Rect (self.x,self.y,72,96+15*max(0, len(self.cards)-1))
        
    def numberOfFaceup(self):
        count = 0
        for card in self.cards:
            if card.faceup: count += 1
        return count
    
    def handleClick(self,event):
        global draggedcard
        #Tests for cards in the piles. If not, then the return skips over the rest of the code
        if 0 == len(self.cards): return
        if self.collapsed:
            numberOfCards = 1
        else:
            #  +-------+
            #  | 30-44 | 15 px
            #  +-------+
            #  | 15-29 | 15 px
            #  +-------+
            #  |  0-14 | 96 px
            #  |       |
            #  |  neg  |
            #  +-------+
            numberOfCards = max((self.rectangle().bottom - 81 - event.pos[1]) / 15, 0) + 1
            # number of cards being dragged
            print numberOfCards
            numberOfCards = min(numberOfCards, self.numberOfFaceup())
        notDragged = len(self.cards)-numberOfCards
        # Takes the length of the cards and then subtracts the number of cards on the pile
        draggedcard = self.cards[-numberOfCards:]
        if self.collapsed:
            deltax = event.pos[0] - self.x
            deltay = event.pos[1] - self.y
        else:
            deltax = event.pos[0] - self.x
            deltay = event.pos[1] - (self.y + 15 * notDragged)
        while event.type != MOUSEBUTTONUP:
            event = pygame.event.wait()
            draw()
            if event.type == MOUSEMOTION:
                y = event.pos[1]-deltay
                for card in draggedcard:
                    card.drawAt(event.pos[0]-deltax,y)
                    y += 15
            pygame.display.update()
        if dropCardAt(event.pos, draggedcard):
            self.cards = self.cards[:-numberOfCards]
            if len(self.cards) > 0:
                self.cards[-1].faceup = True
        draggedcard = []
            
            
lowerPiles = []
for i in range(0, 7):
    lowerPiles.append(Pile(10 + 85*i, 100, False))
    for j in range(0,i+1):
        lowerPiles [i].cards.append(allCards.pop())

for pile in lowerPiles:
    pile.cards[-1].faceup = True

suitPiles = [Pile(520,0,True), Pile(435,0,True), Pile(350,0,True), Pile(265,0,True)]
faceupPile = Pile(95,0,True)
facedownPile = Pile(10,0,True)
print len(allCards)
facedownPile.cards.extend(allCards)

def draw():
    windowSurface.fill(DARKGREEN)
    for i in [CLUBS,SPADES,HEARTS,DIAMONDS]:
        suitPiles[i].draw()
    faceupPile.draw()
    facedownPile.draw()
    for pile in lowerPiles:
        pile.draw()

def dropCardAt(pos, cards):
    for suit in [CLUBS, SPADES, HEARTS, DIAMONDS]:
        if suitPiles[suit].boundingRect().collidepoint(pos):
            if len(suitPiles[suit].cards) == 0:
                if cards[0].suit == suit and cards[0].rank == ACE:
                    suitPiles[suit].cards.extend(cards)
                    return True
                else:
                    return False
            elif cards[0].suit == suit and cards[0].rank == (suitPiles[suit].cards[-1].rank - 1)%13:
                suitPiles[suit].cards.extend(cards)
                return True
    for pile in lowerPiles:
        if pile.rectangle().collidepoint(pos):
            if len(pile.cards) > 0:
                if cards[0].rank == (pile.cards[-1].rank + 1)%13 and cards[0].suit/2 != pile.cards[-1].suit/2:
                    pile.cards.extend(cards)
                    return True
            elif cards[0].rank == KING:
                    pile.cards.extend(cards)
                    return True

def handlemouseevent (event):
    global draggedcard

    #Checking for click in the lowerPiles
    for i in range(0, len(lowerPiles)):
        if lowerPiles[i].boundingRect().collidepoint(event.pos):
            lowerPiles[i].handleClick(event)
    #Checking for click in the faceupPile 
    if faceupPile.boundingRect().collidepoint(event.pos):
        faceupPile.handleClick(event)
    #Checking for click in the Ace piles
    for i in range(0, len(suitPiles)):
        if suitPiles[i].boundingRect().collidepoint(event.pos):
            suitPiles[i].handleClick(event)
    #checking for click and making the pile reset itself        
    if facedownPile.boundingRect().collidepoint(event.pos):
        if len(facedownPile.cards) == 0:
            facedownPile.cards = faceupPile.cards
            facedownPile.cards.reverse()
            faceupPile.cards = []
            for card in facedownPile.cards:
                card.faceup = False
        faceupPile.cards.append(facedownPile.cards.pop())
        faceupPile.cards[-1].faceup = True


    else:
        print "don't know where clicked"

try:
    while True:
        event = pygame.event.poll()
        draw()
        pygame.display.update()
        if event.type == QUIT:
            pygame.quit()
            break
        elif event.type == MOUSEBUTTONDOWN :
            print event
            handlemouseevent (event)
           
except:
    print "Unexpected error:", sys.exc_info()[0]
    pygame.quit()
